-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Redefine browser requirements for modern (latest) builds #16506
Conversation
Should have mentioned that the regex includes all the browsers in the CanIUse.com database, not just the ones listed above. Here's the full test: var isModern = /Edge?\/(1{2}\d|1[2-9]\d|[2-9]\d{2}|\d{4,})(\.\d+|)(\.\d+|)|Firefox\/(10[2-9]|1[1-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Chrom(ium|e)\/(109|1[1-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Maci.+ Version\/(15\.([6-9]|\d{2,})|(1[6-9]|[2-9]\d|\d{3,})\.\d+)([,.]\d+|)( Mobile\/\w+|) Safari\/|Chrome.+OPR\/(9[4-9]|\d{3,})\.\d+\.\d+|(CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS|CPU iPad OS)[ +]+(15[._]([6-9]|\d{2,})|(1[6-9]|[2-9]\d|\d{3,})[._]\d+)([._]\d+|)|Android:?[ /-](1{2}[2-9]|1[2-9]\d|[2-9]\d{2}|\d{4,})(\.\d+|)(\.\d+|)|Mobile Safari.+OPR\/(7[3-9]|[89]\d|\d{3,})\.\d+\.\d+|Android.+Firefox\/(1{2}\d|1[2-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Android.+Chrom(ium|e)\/(1{2}[2-9]|1[2-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Android.+(UC? ?Browser|UCWEB|U3)[ /]?(13\.([4-9]|\d{2,})|(1[4-9]|[2-9]\d|\d{3,})\.\d+)\.\d+|SamsungBrowser\/(19|[2-9]\d|\d{3,})\.\d+|Android.+MQ{2}Browser\/(13(\.([1-9]|\d{2,})|)|(1[4-9]|[2-9]\d|\d{3,})(\.\d+|))(\.\d+|)|K[Aa][Ii]OS\/(3\.\d+|([4-9]|\d{2,})\.\d+)(\.\d+|)/.test(navigator.userAgent); |
ca3a3eb
to
9e55e39
Compare
I feel like these restraints are a bit too much, we are now pushing people to the much bigger and slower ES5 build, while their device/browser is perfectly capable of running on our latest build? Are we fixing certain browsers with this, that now don't work with latest and are moved to ES5? If so what are we fixing and could we target that more precise? If it would really gain us something in terms of performance I would get it, but it seems that isn't the case (at least for now?) |
I'm marking this as a draft because I want to investigate how it treats android mobile versions. The regex is only grabbing the latest version but the docs say it should be treated like desktop. Answering your questions in the meantime...
In terms of size, the 2 builds are actually not that far apart anymore after #16466. Compared to the current release of major browsers, the latest build is actually targeting browsers much closer to the legacy requirements from #16384, and that gap will keep getting smaller without redefining somehow. So this is really just trying to drive a bigger wedge between the 2 builds and eek out as much extra performance and reduced size as possible. Based on the global usage data, this might affect about 5% of users, but that's an estimate for sure. That said, I'm certainly not claiming this is the best position for the wedge so that's worth discussing. I'm not sure how to make it more "accurate" though in the absence of including user agents in the HA analytics data.
Yes. Though it's not turned on right now, we should be allowing Babel to inject core-js polyfills into the latest build in order to fix or support various features, some of which are used frequently. If we did under the current dynamic import test, here's the plugins and polyfills that would be used:
|
FYI, to deal with the android issue, some fixes to
The latter can be worked around temporarily, but the first is a hold up. |
9e55e39
to
16df767
Compare
75008dd
to
d48a9e3
Compare
I submitted fixes to the var isModern = /Edge?\/(10[4-9]|1[1-9]\d|[2-9]\d{2}|\d{4,})(\.\d+|)(\.\d+|)|Firefox\/(10[2-9]|1[1-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Chrom(ium|e)\/(10[4-9]|1[1-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Maci.+ Version\/(15\.([6-9]|\d{2,})|(1[6-9]|[2-9]\d|\d{3,})\.\d+)([,.]\d+|)( Mobile\/\w+|) Safari\/|Chrome.+OPR\/(89|9\d|\d{3,})\.\d+\.\d+|(CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS|CPU iPad OS)[ +]+(15[._]([6-9]|\d{2,})|(1[6-9]|[2-9]\d|\d{3,})[._]\d+)([._]\d+|)|Android:?[ /-](10[4-9]|1[1-9]\d|[2-9]\d{2}|\d{4,})(\.\d+|)(\.\d+|)|Mobile Safari.+OPR\/(7[3-9]|[89]\d|\d{3,})\.\d+\.\d+|Android.+Firefox\/(10[3-9]|1[1-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Android.+Chrom(ium|e)\/(10[4-9]|1[1-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|SamsungBrowser\/(1[89]|[2-9]\d|\d{3,})\.\d+/.test(navigator.userAgent); In fixing the |
In terms of adding more browsers, I think we could safely include anything released in the last year as opposed to just the last 2 versions. The popularity of older iOS versions and inclusion of Firefox ESR keep the transpiling and polyfilling to about a year in the past anyway. Going beyond 1 year I think would be excessive. The other parameter to play with is the usage percentage, but that will start bringing back pretty old stuff depending on the value. For example, > 0.2% goes back to IOS 12 and Chrome 79, adding extra transpiling and polyfilling of course. Thoughts? |
b9cf48b
to
296de5e
Compare
Okay I think this is probably ready to go now:
I updated the OP to reflect all changes. |
bce0e3c
to
b9e5561
Compare
@bramkragten are you generally okay with this approach (minus the exact query to use perhaps)? If so, I can throw together updated documentation for home-assistant/home-assistant.io#27509. |
I don't really like that we will now test on useragent instead of actual features, the useragent can be overriden by a client (Like our apps: iOS & Android) and in general I think it is saver to check for actually features For the exact query to use I think we should try to make something that will gain us enough to justify dropping certain users to a slower version, or make sure we (almost) don't actually drop anything. |
ba0c070
to
a421441
Compare
WalkthroughWalkthroughThe recent changes focus on enhancing performance and compatibility across modern and legacy browsers. Key updates include refining browser targeting in Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Browser
participant Server
User->>Browser: Request page
Browser->>Server: Load HTML template
Server->>Browser: Serve HTML template
Browser->>Browser: Check user agent
alt Modern Browser
Browser->>Server: Load ES6 modules
else Legacy Browser
Browser->>Server: Load ES5 modules
end
Browser->>User: Render page
sequenceDiagram
participant User
participant Browser
participant Server
User->>Browser: Request onboarding
Browser->>Browser: Check window.latestJS
alt latestJS is true
Browser->>Server: Fetch onboarding steps
else latestJS is false
Browser->>Server: Load fallback scripts
end
Browser->>User: Render onboarding page
Recent review detailsConfiguration used: CodeRabbit UI Files ignored due to path filters (1)
Files selected for processing (14)
Files skipped from review as they are similar to previous changes (13)
Additional comments not posted (2)
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (invoked as PR comments)
Additionally, you can add CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Outside diff range comments (1)
build-scripts/bundle.cjs (1)
Line range hint
1-1
: Update import statement to use thenode:
protocol.To align with Node.js best practices, prepend
node:
to the import statement for built-in modules.- const path = require("path"); + const path = require("node:path");
This should be good now but merge #21177 first. I can follow this up with some minor clean up:
|
Adding feature detection was fairly simple so that can be crossed off now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
117b58a
to
1b663ea
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Outside diff range comments (6)
build-scripts/bundle.cjs (6)
Line range hint
1-1
: Use thenode:
protocol for Node.js built-in modules.Using the
node:
protocol is more explicit and signals that the imported module belongs to Node.js.- const path = require("path"); + const path = require("node:path");
Line range hint
222-222
: Use template literals instead of string concatenation.Template literals are preferred over string concatenation for better readability and maintainability.
- return `https://raw.githubusercontent.com/home-assistant/frontend/${ref}/`;
Line range hint
243-243
: Use template literals instead of string concatenation.Template literals are preferred over string concatenation for better readability and maintainability.
- __BUILD__: JSON.stringify(latestBuild ? "latest" : "es5"),
Line range hint
273-273
: Use template literals instead of string concatenation.Template literals are preferred over string concatenation for better readability and maintainability.
- name: "frontend" + nameSuffix(latestBuild), + name: `frontend${nameSuffix(latestBuild)}`,
Line range hint
287-287
: Use template literals instead of string concatenation.Template literals are preferred over string concatenation for better readability and maintainability.
- name: "demo" + nameSuffix(latestBuild), + name: `demo${nameSuffix(latestBuild)}`,
Line range hint
307-307
: Use template literals instead of string concatenation.Template literals are preferred over string concatenation for better readability and maintainability.
- name: "cast" + nameSuffix(latestBuild), + name: `cast${nameSuffix(latestBuild)}`,
1b663ea
to
87280e2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Outside diff range, codebase verification and nitpick comments (3)
hassio/src/entrypoint.js.template (2)
Line range hint
7-16
: Review the use ofnew Function
for dynamic imports.Using
new Function
to handle imports can lead to security risks, such as code injection, if not properly sanitized. It's crucial to ensure that theentry
values are controlled and not susceptible to external manipulation.Consider replacing
new Function
with a more secure method of dynamic importing if possible, or ensure that the inputs (entry
) are rigorously validated.
Line range hint
7-16
: Ensure comprehensive error handling for dynamic imports.The current implementation uses a
try-catch
block to fall back to ES5 loading if the ES6 import fails. This is a good practice as it ensures that the application can still function if modern modules fail to load. However, it might be beneficial to log these errors for debugging and monitoring purposes.try { <% for (const entry of latestEntryJS) { %> new Function("import('<%= entry %>')")(); <% } %> } catch (err) { + console.error("Failed to load modern entries:", err); <% for (const entry of es5EntryJS) { %> loadES5("<%= entry %>"); <% } %> }
Also applies to: 17-19
cast/src/html/index.html.template (1)
18-18
: Google Analytics Script ReviewThe Google Analytics script is correctly implemented to track page views. However, consider the implications of user privacy and ensure compliance with GDPR if applicable.
Co-authored-by: Quentame <[email protected]>
87280e2
to
f1214e4
Compare
GitHub should have an achievement award for number of conflicts fixed on a single PR... |
Breaking change
Browser requirements for serving modern (latest) builds of the frontend have been updated to include only those released in the last year or those still having high global utilization above 0.5%. As before, legacy builds will be served whenever modern requirements are not met.
Proposed change
This change implements a new and more practical way to decipher between "modern" and "legacy" browsers by:
browserslist
query to be more practical and evolve to always grab the most recent/utilized browser versions. This does for the modern builds what Redefine browser requirements for legacy (ES5) builds #16384 did for legacy.import()
syntax test is kept for simplicity of these changes and as a backup for now, but I think it can be safely eliminated in order to consolidate and simplify the loading code in a future PR.This does turn off most of Babel's transforms, but only reduces the bundle by about 1%. Of course that doesn't account for the fact that the current dynamic import test technically includes some pretty old browsers that should have a bunch of polyfills, so not really a fair comparison. Also, a not-so-modest reduction might be obtained by not having to transpile class fields, but Lit's decorators are still on the stage 2 spec.
Lastly, I did try to consolidate more code in the templates. The exception was the app index because of its special treatment, but I can fix that in a follow up.
New requirements as of today would be at least (updated to reflect changes from discussion below):
* = only latest version due to limitations of CanIUse database
Modern Build Babel Plugins
@babel/preset-env:
DEBUG
optionUsing targets:
{
"android": "115",
"chrome": "109",
"edge": "115",
"firefox": "115",
"ios": "15.6",
"opera": "101",
"opera_mobile": "80",
"safari": "16.6",
"samsung": "22"
}
Using modules transform: auto
Using plugins:
transform-unicode-sets-regex { chrome < 112, firefox < 116, ios < 17, safari < 17, samsung }
bugfix/transform-firefox-class-in-computed-class-key { firefox }
proposal-class-static-block { ios < 16.4 }
syntax-private-property-in-object
syntax-class-properties
syntax-numeric-separator
syntax-nullish-coalescing-operator
syntax-optional-chaining
syntax-json-strings
syntax-optional-catch-binding
syntax-async-generators
syntax-object-rest-spread
syntax-export-namespace-from
bugfix/transform-safari-id-destructuring-collision-in-function-expression { ios < 16.3 }
syntax-dynamic-import
syntax-top-level-await
syntax-import-meta
syntax-import-attributes
Modern Build Core-JS Polyfills
The following 56 polyfills may be injected by Babel:
es.array.push { android < 122, chrome < 122, edge < 122, ios < 16.0, opera < 108, opera_mobile < 81, samsung < 26.0 }
es.array.to-reversed { chrome < 110, ios < 16.0 }
es.array.to-sorted { chrome < 110, ios < 16.0 }
es.array.to-spliced { chrome < 110, ios < 16.0 }
es.array.unshift { ios < 16.0 }
es.array.with { chrome < 110, ios < 16.0 }
es.array-buffer.detached { chrome < 114, firefox < 122, ios < 17.4, safari < 17.4, samsung < 23.0 }
es.array-buffer.transfer { chrome < 114, firefox < 122, ios < 17.4, safari < 17.4, samsung < 23.0 }
es.array-buffer.transfer-to-fixed-length { chrome < 114, firefox < 122, ios < 17.4, safari < 17.4, samsung < 23.0 }
es.map.group-by { android < 117, chrome < 117, edge < 117, firefox < 119, ios, opera < 103, safari, samsung < 24.0 }
es.object.group-by { android < 117, chrome < 117, edge < 117, firefox < 119, ios, opera < 103, safari, samsung < 24.0 }
es.promise.with-resolvers { android < 119, chrome < 119, edge < 119, firefox < 121, ios < 17.4, opera < 105, safari < 17.4, samsung < 25.0 }
es.regexp.flags { chrome < 111 }
es.set.difference.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.set.intersection.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.set.is-disjoint-from.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.set.is-subset-of.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.set.is-superset-of.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.set.symmetric-difference.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.set.union.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.string.is-well-formed { chrome < 111, firefox < 119, ios < 16.4 }
es.string.to-well-formed { chrome < 111, firefox < 119, ios < 16.4 }
es.typed-array.to-reversed { chrome < 110, ios < 16.0 }
es.typed-array.to-sorted { chrome < 110, ios < 16.0 }
es.typed-array.with { chrome < 110, ios < 16.4 }
esnext.suppressed-error.constructor { android, chrome, edge, firefox, ios, opera, opera_mobile, safari, samsung }
esnext.array.from-async { android < 121, chrome < 121, edge < 121, ios, opera < 107, opera_mobile < 81, safari, samsung < 25.0 }
esnext.array.group { android, chrome, edge, firefox, ios, opera, opera_mobile, safari, samsung }
esnext.array.group-to-map { android, chrome, edge, firefox, ios, opera, opera_mobile, safari, samsung }
esnext.iterator.constructor { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.drop { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.every { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.filter { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.find { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.flat-map { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.for-each { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.from { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.map { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.reduce { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.some { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.take { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.to-array { android < 122, chrome < 122, edge < 122, firefox, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.json.is-raw-json { chrome < 114, firefox, ios, safari, samsung < 23.0 }
esnext.json.parse { chrome < 114, firefox, ios, safari, samsung < 23.0 }
esnext.json.raw-json { chrome < 114, firefox, ios, safari, samsung < 23.0 }
esnext.symbol.async-dispose { android, chrome, edge, firefox, ios, opera, opera_mobile, safari, samsung }
esnext.symbol.dispose { android < 125, chrome < 125, edge < 125, firefox, ios, opera < 111, opera_mobile, safari, samsung }
esnext.symbol.metadata { android, chrome, edge, firefox, ios, opera, opera_mobile, safari, samsung }
web.dom-exception.stack { android, chrome, edge, ios, opera, opera_mobile, safari, samsung }
web.immediate { android, chrome, edge, firefox, ios, opera, opera_mobile, safari, samsung }
web.structured-clone { android, chrome, edge, firefox, ios, opera, opera_mobile, safari, samsung }
web.url.can-parse { android < 120, chrome < 120, edge < 120, ios < 17.0, opera < 106, safari < 17.0, samsung < 25.0 }
web.url.parse { android < 126, chrome < 126, edge < 126, firefox < 126, ios, opera < 112, opera_mobile, safari, samsung }
web.url-search-params.delete { android < 118, chrome < 118, edge < 118, ios < 17.0, opera < 104, safari < 17.0, samsung < 25.0 }
web.url-search-params.has { android < 118, chrome < 118, edge < 118, ios < 17.0, opera < 104, safari < 17.0, samsung < 25.0 }
web.url-search-params.size { chrome < 113, ios < 17.0, safari < 17.0, samsung < 23.0 }
Legacy Build Babel Plugins
@babel/preset-env:
DEBUG
optionUsing targets:
{
"android": "60",
"chrome": "60",
"edge": "16",
"firefox": "52",
"ie": "11",
"ios": "10.3",
"opera": "47",
"opera_mobile": "80",
"safari": "11",
"samsung": "4"
}
Using modules transform: auto
Using plugins:
transform-unicode-sets-regex { android, chrome < 112, edge < 112, firefox < 116, ie, ios < 17, opera < 98, safari < 17, samsung }
proposal-class-static-block { android, chrome < 94, edge < 94, firefox < 93, ie, ios < 16.4, opera < 80, safari < 16.4, samsung < 17 }
proposal-private-property-in-object { android, chrome < 91, edge < 91, firefox < 90, ie, ios < 15, opera < 77, safari < 15, samsung < 16 }
proposal-class-properties { android, chrome < 74, edge < 79, firefox < 90, ie, ios < 14.5, opera < 62, safari < 14.1, samsung < 11 }
proposal-private-methods { android, chrome < 84, edge < 84, firefox < 90, ie, ios < 15, opera < 70, safari < 15, samsung < 14 }
proposal-numeric-separator { android, chrome < 75, edge < 79, firefox < 70, ie, ios < 13, opera < 62, safari < 13, samsung < 11 }
proposal-logical-assignment-operators { android, chrome < 85, edge < 85, firefox < 79, ie, ios < 14, opera < 71, safari < 14, samsung < 14 }
proposal-nullish-coalescing-operator { android, chrome < 80, edge < 80, firefox < 72, ie, ios < 13.4, opera < 67, safari < 13.1, samsung < 13 }
proposal-optional-chaining { android, chrome < 80, edge < 80, firefox < 74, ie, ios < 13.4, opera < 67, safari < 13.1, samsung < 13 }
proposal-json-strings { android, chrome < 66, edge < 79, firefox < 62, ie, ios < 12, opera < 53, safari < 12, samsung < 9 }
proposal-optional-catch-binding { android, chrome < 66, edge < 79, firefox < 58, ie, ios < 11.3, opera < 53, safari < 11.1, samsung < 9 }
transform-parameters { firefox < 53, ie, samsung < 5 }
proposal-async-generator-functions { android, chrome < 63, edge < 79, firefox < 57, ie, ios < 12, opera < 50, safari < 12, samsung < 8 }
proposal-object-rest-spread { edge < 79, firefox < 55, ie, ios < 11.3, safari < 11.1, samsung < 8 }
transform-dotall-regex { android, chrome < 62, edge < 79, firefox < 78, ie, ios < 11.3, opera < 49, safari < 11.1, samsung < 8 }
proposal-unicode-property-regex { android, chrome < 64, edge < 79, firefox < 78, ie, ios < 11.3, opera < 51, safari < 11.1, samsung < 9 }
transform-named-capturing-groups-regex { android, chrome < 64, edge < 79, firefox < 78, ie, ios < 11.3, opera < 51, safari < 11.1, samsung < 9 }
transform-async-to-generator { ie, samsung < 6 }
transform-exponentiation-operator { ie, samsung < 6 }
transform-template-literals { ie }
transform-literals { firefox < 53, ie }
transform-function-name { firefox < 53, ie, samsung < 5 }
transform-arrow-functions { ie, samsung < 5 }
transform-classes { ie, samsung < 5 }
transform-object-super { ie, samsung < 5 }
transform-shorthand-properties { ie }
transform-duplicate-keys { ie }
transform-computed-properties { ie }
transform-for-of { firefox < 53, ie, samsung < 5 }
transform-sticky-regex { ie, samsung < 5 }
transform-unicode-escapes { firefox < 53, ie }
transform-unicode-regex { ie, ios < 12, safari < 12, samsung < 5 }
transform-spread { ie, samsung < 5 }
transform-destructuring { firefox < 53, ie, samsung < 5 }
transform-block-scoping { firefox < 53, ie, samsung < 5 }
transform-typeof-symbol { ie }
transform-new-target { ie, samsung < 5 }
transform-regenerator { firefox < 53, ie, samsung < 5 }
proposal-export-namespace-from { android < 72, chrome < 72, edge < 79, firefox < 80, ie, ios < 14.5, opera < 60, safari < 14.1, samsung < 11.0 }
syntax-dynamic-import
syntax-top-level-await
syntax-import-meta
syntax-import-attributes
Legacy Build Core-JS Polyfills
The following 273 polyfills may be injected by Babel:
es.symbol { ie, samsung < 5.0 }
es.symbol.description { android < 70, chrome < 70, edge < 79, firefox < 63, ie, ios < 12.2, opera < 57, safari < 12.1, samsung < 10.0 }
es.symbol.async-iterator { android < 63, chrome < 63, edge < 79, firefox < 55, ie, ios < 12.0, opera < 50, safari < 12.0, samsung < 8.0 }
es.symbol.has-instance { ie, samsung < 5.0 }
es.symbol.is-concat-spreadable { ie, samsung < 5.0 }
es.symbol.iterator { ie }
es.symbol.match { edge < 79, ie, samsung < 5.0 }
es.symbol.match-all { android < 73, chrome < 73, edge < 79, firefox < 67, ie, ios < 13.0, opera < 60, safari < 13, samsung < 11.0 }
es.symbol.replace { edge < 79, ie, samsung < 5.0 }
es.symbol.search { edge < 79, ie, samsung < 5.0 }
es.symbol.species { ie, samsung < 5.0 }
es.symbol.split { edge < 79, ie, samsung < 5.0 }
es.symbol.to-primitive { ie, samsung < 5.0 }
es.symbol.to-string-tag { ie, samsung < 5.0 }
es.symbol.unscopables { ie }
es.error.cause { android < 94, chrome < 94, edge < 94, firefox < 91, ie, ios < 15.0, opera < 80, safari < 15.0, samsung < 17.0 }
es.aggregate-error { android < 85, chrome < 85, edge < 85, firefox < 79, ie, ios < 14.0, opera < 71, safari < 14.0, samsung < 14.0 }
es.aggregate-error.cause { android < 94, chrome < 94, edge < 94, firefox < 91, ie, ios < 15.0, opera < 80, safari < 15.0, samsung < 17.0 }
es.array.at { android < 92, chrome < 92, edge < 92, firefox < 90, ie, ios < 15.4, opera < 78, safari < 15.4, samsung < 16.0 }
es.array.concat { ie, samsung < 5.0 }
es.array.copy-within { ie, samsung < 5.0 }
es.array.fill { ie, samsung < 5.0 }
es.array.filter { ie, samsung < 5.0 }
es.array.find { ie, samsung < 5.0 }
es.array.find-index { ie, samsung < 5.0 }
es.array.find-last { android < 97, chrome < 97, edge < 97, firefox < 104, ie, ios < 15.4, opera < 83, safari < 15.4, samsung < 18.0 }
es.array.find-last-index { android < 97, chrome < 97, edge < 97, firefox < 104, ie, ios < 15.4, opera < 83, safari < 15.4, samsung < 18.0 }
es.array.flat { android < 69, chrome < 69, edge < 79, firefox < 62, ie, ios < 12.0, opera < 56, safari < 12.0, samsung < 10.0 }
es.array.flat-map { android < 69, chrome < 69, edge < 79, firefox < 62, ie, ios < 12.0, opera < 56, safari < 12.0, samsung < 10.0 }
es.array.from { firefox < 53, ie, samsung < 5.0 }
es.array.includes { firefox < 102, ie, samsung < 6.0 }
es.array.index-of { samsung < 5.0 }
es.array.iterator { android < 66, chrome < 66, firefox < 60, ie, opera < 53, samsung < 9.0 }
es.array.join { ie }
es.array.last-index-of { samsung < 5.0 }
es.array.map { ie, samsung < 5.0 }
es.array.of { ie, samsung < 5.0 }
es.array.push { android < 122, chrome < 122, edge < 122, firefox < 55, ie, ios < 16.0, opera < 108, opera_mobile < 81, safari < 16.0, samsung < 26.0 }
es.array.reduce { android < 83, chrome < 83, opera < 69, samsung < 13.0 }
es.array.reduce-right { android < 83, chrome < 83, opera < 69, samsung < 13.0 }
es.array.reverse { ios < 12.2, safari < 12.0.2 }
es.array.slice { ie, samsung < 5.0 }
es.array.sort { android < 70, chrome < 70, edge < 79, ie, ios < 12.0, opera < 57, safari < 12.0, samsung < 10.0 }
es.array.species { ie, samsung < 5.0 }
es.array.splice { ie, samsung < 5.0 }
es.array.to-reversed { android < 110, chrome < 110, edge < 110, firefox < 115, ie, ios < 16.0, opera < 96, safari < 16.0, samsung < 21.0 }
es.array.to-sorted { android < 110, chrome < 110, edge < 110, firefox < 115, ie, ios < 16.0, opera < 96, safari < 16.0, samsung < 21.0 }
es.array.to-spliced { android < 110, chrome < 110, edge < 110, firefox < 115, ie, ios < 16.0, opera < 96, safari < 16.0, samsung < 21.0 }
es.array.unscopables.flat { android < 73, chrome < 73, edge < 79, firefox < 67, ie, ios < 13.0, opera < 60, safari < 13, samsung < 11.0 }
es.array.unscopables.flat-map { android < 73, chrome < 73, edge < 79, firefox < 67, ie, ios < 13.0, opera < 60, safari < 13, samsung < 11.0 }
es.array.unshift { android < 71, chrome < 71, ios < 16.0, opera < 58, safari < 16.0, samsung < 10.0 }
es.array.with { android < 110, chrome < 110, edge < 110, firefox < 115, ie, ios < 16.0, opera < 96, safari < 16.0, samsung < 21.0 }
es.array-buffer.constructor { ie, ios < 12.0, safari < 12.0 }
es.array-buffer.slice { ios < 12.2, safari < 12.1 }
es.array-buffer.detached { android < 114, chrome < 114, edge < 114, firefox < 122, ie, ios < 17.4, opera < 100, safari < 17.4, samsung < 23.0 }
es.array-buffer.transfer { android < 114, chrome < 114, edge < 114, firefox < 122, ie, ios < 17.4, opera < 100, safari < 17.4, samsung < 23.0 }
es.array-buffer.transfer-to-fixed-length { android < 114, chrome < 114, edge < 114, firefox < 122, ie, ios < 17.4, opera < 100, safari < 17.4, samsung < 23.0 }
es.date.to-primitive { ie, samsung < 5.0 }
es.function.has-instance { ie, samsung < 5.0 }
es.function.name { ie }
es.global-this { android < 71, chrome < 71, edge < 79, firefox < 65, ie, ios < 12.2, opera < 58, safari < 12.1, samsung < 10.0 }
es.json.stringify { android < 72, chrome < 72, edge < 79, firefox < 64, ie, ios < 12.2, opera < 59, safari < 12.1, samsung < 11.0 }
es.json.to-string-tag { ie, samsung < 5.0 }
es.map { firefox < 53, ie, samsung < 5.0 }
es.map.group-by { android < 117, chrome < 117, edge < 117, firefox < 119, ie, ios, opera < 103, safari, samsung < 24.0 }
es.math.acosh { ie, samsung < 6.0 }
es.math.asinh { ie }
es.math.atanh { ie }
es.math.cbrt { ie }
es.math.clz32 { ie }
es.math.cosh { ie }
es.math.expm1 { ie }
es.math.fround { ie }
es.math.hypot { android < 78, chrome < 78, ie, opera < 65, samsung < 12.0 }
es.math.imul { ie }
es.math.log10 { ie }
es.math.log1p { ie }
es.math.log2 { ie }
es.math.sign { ie }
es.math.sinh { ie }
es.math.tanh { ie }
es.math.to-string-tag { ie, samsung < 5.0 }
es.math.trunc { ie }
es.number.constructor { ie }
es.number.epsilon { ie }
es.number.is-finite { ie }
es.number.is-integer { ie }
es.number.is-nan { ie }
es.number.is-safe-integer { ie }
es.number.max-safe-integer { ie }
es.number.min-safe-integer { ie }
es.number.parse-float { edge < 79, ie, ios < 11.0 }
es.number.parse-int { edge < 79, ie }
es.number.to-exponential { edge < 18, firefox < 87, ie, ios < 11.0, samsung < 5.0 }
es.number.to-fixed { edge < 79, ie }
es.object.assign { edge < 79, ie, samsung < 5.0 }
es.object.define-getter { android < 62, chrome < 62, ie, opera < 49, samsung < 8.0 }
es.object.define-setter { android < 62, chrome < 62, ie, opera < 49, samsung < 8.0 }
es.object.entries { ie, samsung < 6.0 }
es.object.freeze { ie }
es.object.from-entries { android < 73, chrome < 73, edge < 79, firefox < 63, ie, ios < 12.2, opera < 60, safari < 12.1, samsung < 11.0 }
es.object.get-own-property-descriptor { ie }
es.object.get-own-property-descriptors { ie, samsung < 6.0 }
es.object.get-own-property-names { ie }
es.object.get-prototype-of { ie }
es.object.group-by { android < 117, chrome < 117, edge < 117, firefox < 119, ie, ios, opera < 103, safari, samsung < 24.0 }
es.object.has-own { android < 93, chrome < 93, edge < 93, firefox < 92, ie, ios < 15.4, opera < 79, safari < 15.4, samsung < 17.0 }
es.object.is { ie }
es.object.is-extensible { ie }
es.object.is-frozen { ie }
es.object.is-sealed { ie }
es.object.keys { ie }
es.object.lookup-getter { android < 62, chrome < 62, ie, opera < 49, samsung < 8.0 }
es.object.lookup-setter { android < 62, chrome < 62, ie, opera < 49, samsung < 8.0 }
es.object.prevent-extensions { ie }
es.object.seal { ie }
es.object.to-string { ie, samsung < 5.0 }
es.object.values { ie, samsung < 6.0 }
es.parse-float { edge < 74 }
es.parse-int { edge < 74 }
es.promise { android < 67, chrome < 67, edge < 79, firefox < 69, ie, ios < 11.0, opera < 54, samsung < 9.0 }
es.promise.all-settled { android < 76, chrome < 76, edge < 79, firefox < 71, ie, ios < 13.0, opera < 63, safari < 13, samsung < 12.0 }
es.promise.any { android < 85, chrome < 85, edge < 85, firefox < 79, ie, ios < 14.0, opera < 71, safari < 14.0, samsung < 14.0 }
es.promise.finally { android < 67, chrome < 67, edge < 79, firefox < 69, ie, ios < 13.2.3, opera < 54, safari < 13.0.3, samsung < 9.0 }
es.promise.with-resolvers { android < 119, chrome < 119, edge < 119, firefox < 121, ie, ios < 17.4, opera < 105, safari < 17.4, samsung < 25.0 }
es.reflect.apply { ie, samsung < 5.0 }
es.reflect.construct { ie, samsung < 5.0 }
es.reflect.define-property { ie, samsung < 5.0 }
es.reflect.delete-property { ie, samsung < 5.0 }
es.reflect.get { ie, samsung < 5.0 }
es.reflect.get-own-property-descriptor { ie, samsung < 5.0 }
es.reflect.get-prototype-of { ie, samsung < 5.0 }
es.reflect.has { ie, samsung < 5.0 }
es.reflect.is-extensible { ie, samsung < 5.0 }
es.reflect.own-keys { ie, samsung < 5.0 }
es.reflect.prevent-extensions { ie, samsung < 5.0 }
es.reflect.set { edge < 79, ie, samsung < 5.0 }
es.reflect.set-prototype-of { ie, samsung < 5.0 }
es.reflect.to-string-tag { android < 86, chrome < 86, edge < 86, firefox < 82, ie, ios < 14.0, opera < 72, safari < 14.0, samsung < 14.0 }
es.regexp.constructor { android < 64, chrome < 64, edge < 79, firefox < 78, ie, ios < 11.3, opera < 51, safari < 11.1, samsung < 9.0 }
es.regexp.dot-all { android < 62, chrome < 62, edge < 79, firefox < 78, ie, ios < 11.3, opera < 49, safari < 11.1, samsung < 8.0 }
es.regexp.exec { android < 64, chrome < 64, edge < 79, firefox < 78, ie, ios < 11.3, opera < 51, safari < 11.1, samsung < 9.0 }
es.regexp.flags { android < 111, chrome < 111, edge < 111, firefox < 78, ie, ios < 11.3, opera < 97, safari < 11.1, samsung < 22.0 }
es.regexp.sticky { ie, samsung < 5.0 }
es.regexp.test { edge < 79, ie, samsung < 5.0 }
es.regexp.to-string { edge < 79, ie, samsung < 5.0 }
es.set { firefox < 53, ie, samsung < 5.0 }
es.set.difference.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ie, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.set.intersection.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ie, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.set.is-disjoint-from.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ie, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.set.is-subset-of.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ie, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.set.is-superset-of.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ie, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.set.symmetric-difference.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ie, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.set.union.v2 { android < 123, chrome < 123, edge < 123, firefox < 127, ie, ios, opera < 109, opera_mobile < 82, safari, samsung }
es.string.at-alternative { android < 92, chrome < 92, edge < 92, firefox < 90, ie, ios < 15.4, opera < 78, safari < 15.4, samsung < 16.0 }
es.string.code-point-at { ie }
es.string.ends-with { edge < 79, ie, samsung < 5.0 }
es.string.from-code-point { ie }
es.string.includes { edge < 79, ie, samsung < 5.0 }
es.string.is-well-formed { android < 111, chrome < 111, edge < 111, firefox < 119, ie, ios < 16.4, opera < 97, safari < 16.4, samsung < 22.0 }
es.string.iterator { ie }
es.string.match { edge < 79, ie, samsung < 5.0 }
es.string.match-all { android < 80, chrome < 80, edge < 80, firefox < 73, ie, ios < 13.4, opera < 67, safari < 13.1, samsung < 13.0 }
es.string.pad-end { ie, ios < 11.0, samsung < 7.0 }
es.string.pad-start { ie, ios < 11.0, samsung < 7.0 }
es.string.raw { ie }
es.string.repeat { ie }
es.string.replace { android < 64, chrome < 64, edge < 79, firefox < 78, ie, ios < 14.0, opera < 51, safari < 14.0, samsung < 9.0 }
es.string.replace-all { android < 85, chrome < 85, edge < 85, firefox < 77, ie, ios < 13.4, opera < 71, safari < 13.1, samsung < 14.0 }
es.string.search { edge < 79, ie, samsung < 5.0 }
es.string.split { edge < 79, ie, samsung < 6.0 }
es.string.starts-with { edge < 79, ie, samsung < 5.0 }
es.string.to-well-formed { android < 111, chrome < 111, edge < 111, firefox < 119, ie, ios < 16.4, opera < 97, safari < 16.4, samsung < 22.0 }
es.string.trim { ie, ios < 12.2, safari < 12.1, samsung < 7.0 }
es.string.trim-end { android < 66, chrome < 66, edge < 79, firefox < 61, ie, ios < 12.2, opera < 53, safari < 12.1, samsung < 9.0 }
es.string.trim-start { android < 66, chrome < 66, edge < 79, firefox < 61, ie, ios < 12.0, opera < 53, safari < 12.0, samsung < 9.0 }
es.string.anchor { ie }
es.string.big { ie }
es.string.blink { ie }
es.string.bold { ie }
es.string.fixed { ie }
es.string.fontcolor { ie }
es.string.fontsize { ie }
es.string.italics { ie }
es.string.link { ie }
es.string.small { ie }
es.string.strike { ie }
es.string.sub { ie }
es.string.sup { ie }
es.typed-array.float32-array { firefox < 55, ie, ios < 14.0, safari < 14.0, samsung < 6.0 }
es.typed-array.float64-array { firefox < 55, ie, ios < 14.0, safari < 14.0, samsung < 6.0 }
es.typed-array.int8-array { firefox < 55, ie, ios < 14.0, safari < 14.0, samsung < 6.0 }
es.typed-array.int16-array { firefox < 55, ie, ios < 14.0, safari < 14.0, samsung < 6.0 }
es.typed-array.int32-array { firefox < 55, ie, ios < 14.0, safari < 14.0, samsung < 6.0 }
es.typed-array.uint8-array { firefox < 55, ie, ios < 14.0, safari < 14.0, samsung < 6.0 }
es.typed-array.uint8-clamped-array { firefox < 55, ie, ios < 14.0, safari < 14.0, samsung < 6.0 }
es.typed-array.uint16-array { firefox < 55, ie, ios < 14.0, safari < 14.0, samsung < 6.0 }
es.typed-array.uint32-array { firefox < 55, ie, ios < 14.0, safari < 14.0, samsung < 6.0 }
es.typed-array.at { android < 92, chrome < 92, edge < 92, firefox < 90, ie, ios < 15.4, opera < 78, safari < 15.4, samsung < 16.0 }
es.typed-array.copy-within { ie, samsung < 5.0 }
es.typed-array.every { ie, samsung < 5.0 }
es.typed-array.fill { edge < 79, firefox < 55, ie, ios < 14.5, safari < 14.1, samsung < 7.0 }
es.typed-array.filter { ie, samsung < 5.0 }
es.typed-array.find { ie, samsung < 5.0 }
es.typed-array.find-index { ie, samsung < 5.0 }
es.typed-array.find-last { android < 97, chrome < 97, edge < 97, firefox < 104, ie, ios < 15.4, opera < 83, safari < 15.4, samsung < 18.0 }
es.typed-array.find-last-index { android < 97, chrome < 97, edge < 97, firefox < 104, ie, ios < 15.4, opera < 83, safari < 15.4, samsung < 18.0 }
es.typed-array.for-each { ie, samsung < 5.0 }
es.typed-array.from { firefox < 55, ie, ios < 14.0, safari < 14.0, samsung < 6.0 }
es.typed-array.includes { ie, samsung < 5.0 }
es.typed-array.index-of { ie, samsung < 5.0 }
es.typed-array.iterator { ie, samsung < 5.0 }
es.typed-array.join { ie, samsung < 5.0 }
es.typed-array.last-index-of { ie, samsung < 5.0 }
es.typed-array.map { ie, samsung < 5.0 }
es.typed-array.of { firefox < 55, ie, ios < 14.0, safari < 14.0, samsung < 6.0 }
es.typed-array.reduce { ie, samsung < 5.0 }
es.typed-array.reduce-right { ie, samsung < 5.0 }
es.typed-array.reverse { ie, samsung < 5.0 }
es.typed-array.set { android < 95, chrome < 95, edge < 95, firefox < 54, ie, ios < 14.5, opera < 81, safari < 14.1, samsung < 17.0 }
es.typed-array.slice { ie, samsung < 5.0 }
es.typed-array.some { ie, samsung < 5.0 }
es.typed-array.sort { android < 74, chrome < 74, edge < 79, firefox < 67, ie, ios < 14.5, opera < 61, safari < 14.1, samsung < 11.0 }
es.typed-array.subarray { ie }
es.typed-array.to-locale-string { edge < 79, ie, samsung < 5.0 }
es.typed-array.to-reversed { android < 110, chrome < 110, edge < 110, firefox < 115, ie, ios < 16.0, opera < 96, safari < 16.0, samsung < 21.0 }
es.typed-array.to-sorted { android < 110, chrome < 110, edge < 110, firefox < 115, ie, ios < 16.0, opera < 96, safari < 16.0, samsung < 21.0 }
es.typed-array.to-string { ie, samsung < 5.0 }
es.typed-array.with { android < 110, chrome < 110, edge < 110, firefox < 115, ie, ios < 16.4, opera < 96, safari < 16.4, samsung < 21.0 }
es.weak-map { edge < 79, firefox < 53, ie, samsung < 5.0 }
es.weak-set { firefox < 53, ie, samsung < 5.0 }
esnext.suppressed-error.constructor { android, chrome, edge, firefox, ie, ios, opera, opera_mobile, safari, samsung }
esnext.array.from-async { android < 121, chrome < 121, edge < 121, firefox < 115, ie, ios, opera < 107, opera_mobile < 81, safari, samsung < 25.0 }
esnext.array.group { android, chrome, edge, firefox, ie, ios, opera, opera_mobile, safari, samsung }
esnext.array.group-to-map { android, chrome, edge, firefox, ie, ios, opera, opera_mobile, safari, samsung }
esnext.iterator.constructor { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.drop { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.every { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.filter { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.find { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.flat-map { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.for-each { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.from { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.map { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.reduce { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.some { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.take { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.iterator.to-array { android < 122, chrome < 122, edge < 122, firefox, ie, ios, opera < 108, opera_mobile < 81, safari, samsung < 26.0 }
esnext.json.is-raw-json { android < 114, chrome < 114, edge < 114, firefox, ie, ios, opera < 100, safari, samsung < 23.0 }
esnext.json.parse { android < 114, chrome < 114, edge < 114, firefox, ie, ios, opera < 100, safari, samsung < 23.0 }
esnext.json.raw-json { android < 114, chrome < 114, edge < 114, firefox, ie, ios, opera < 100, safari, samsung < 23.0 }
esnext.symbol.async-dispose { android, chrome, edge, firefox, ie, ios, opera, opera_mobile, safari, samsung }
esnext.symbol.dispose { android < 125, chrome < 125, edge < 125, firefox, ie, ios, opera < 111, opera_mobile, safari, samsung }
esnext.symbol.metadata { android, chrome, edge, firefox, ie, ios, opera, opera_mobile, safari, samsung }
web.atob { ie }
web.btoa { ie }
web.dom-collections.for-each { ie, samsung < 7.0 }
web.dom-collections.iterator { android < 66, chrome < 66, edge < 79, firefox < 60, ie, ios < 13.4, opera < 53, safari < 13.1, samsung < 9.0 }
web.dom-exception.constructor { edge < 79, ie, ios < 11.3, safari < 11.1, samsung < 5.0 }
web.dom-exception.stack { android, chrome, edge, ie, ios, opera, opera_mobile, safari, samsung }
web.dom-exception.to-string-tag { edge < 79, ie, ios < 11.3, safari < 11.1, samsung < 5.0 }
web.immediate { android, chrome, edge, firefox, ios, opera, opera_mobile, safari, samsung }
web.queue-microtask { android < 71, chrome < 71, edge < 79, firefox < 69, ie, ios < 12.2, opera < 58, safari < 12.1, samsung < 10.0 }
web.self { android < 86, chrome < 86, edge < 86, ie, opera < 72, samsung < 14.0 }
web.structured-clone { android, chrome, edge, firefox, ie, ios, opera, opera_mobile, safari, samsung }
web.url { android < 67, chrome < 67, edge < 79, firefox < 57, ie, ios < 14.0, opera < 54, safari < 14.0, samsung < 9.0 }
web.url.can-parse { android < 120, chrome < 120, edge < 120, firefox < 115, ie, ios < 17.0, opera < 106, safari < 17.0, samsung < 25.0 }
web.url.parse { android < 126, chrome < 126, edge < 126, firefox < 126, ie, ios, opera < 112, opera_mobile, safari, samsung }
web.url.to-json { android < 71, chrome < 71, edge < 79, firefox < 57, ie, ios < 14.0, opera < 58, safari < 14.0, samsung < 10.0 }
web.url-search-params { android < 67, chrome < 67, edge < 79, firefox < 57, ie, ios < 14.0, opera < 54, safari < 14.0, samsung < 9.0 }
web.url-search-params.delete { android < 118, chrome < 118, edge < 118, firefox < 115, ie, ios < 17.0, opera < 104, safari < 17.0, samsung < 25.0 }
web.url-search-params.has { android < 118, chrome < 118, edge < 118, firefox < 115, ie, ios < 17.0, opera < 104, safari < 17.0, samsung < 25.0 }
web.url-search-params.size { android < 113, chrome < 113, edge < 113, firefox < 112, ie, ios < 17.0, opera < 99, safari < 17.0, samsung < 23.0 }
Type of change
Example configuration
Additional information
Checklist
If user exposed functionality or configuration variables are added/changed:
Summary by CodeRabbit
New Features
Chores
browserslist-useragent-regexp
.These updates aim to provide a smoother, faster experience across a wider range of browsers while maintaining support for older versions.